#include "BoundingBox.h"

BoundingBox::BoundingBox(void)
{
}

BoundingBox::~BoundingBox(void)
{
}

/*
 * return vector<Point3>(2) - The entry and exit intersection points stored respectively
 */
vector<Point3> BoundingBox::rayIntersections(Ray r){
	r.direction.normalize();
	vector<Point3> validIntersections;
	double tempU;
	Point3 tempIntersection;
	//Note: magnitude is ignored because the same intersection points will result regardless.
	Vector3 n1, n2, n3, n4, n5, n6;
	n1 = n2 = Vector3(0, 0, 1);
	n3 = n4 = Vector3(0, 1, 0);
	n5 = n6 = Vector3(1, 0, 0);

	//Check if side 1 intersects (front face)
	if(r.direction * n1 != 0){
		tempU = ((n1*(minValues-r.origin))/(r.direction*n1));
		tempIntersection = r.origin+tempU*r.direction;
		if(tempIntersection.x >= minValues.x && tempIntersection.x <= maxValues.x &&
		   tempIntersection.y >= minValues.y && tempIntersection.y <= maxValues.y){
			validIntersections.push_back(tempIntersection);
		}
	}
	//Check if side 2 intersects (back face)
	if(r.direction * n2 != 0){
		tempU = ((n2*(maxValues-r.origin))/(r.direction*n2));
		tempIntersection = r.origin+tempU*r.direction;
		if(tempIntersection.x >= minValues.x && tempIntersection.x <= maxValues.x &&
		   tempIntersection.y >= minValues.y && tempIntersection.y <= maxValues.y){
			validIntersections.push_back(tempIntersection);
		}
	}
	//Check if side 3 intersects (top face)
	if(r.direction * n3 != 0){
		tempU = ((n3*(maxValues-r.origin))/(r.direction*n3));
		tempIntersection = r.origin+tempU*r.direction;
		if(tempIntersection.x >= minValues.x && tempIntersection.x <= maxValues.x &&
		   tempIntersection.z >= minValues.z && tempIntersection.z <= maxValues.z){
			validIntersections.push_back(tempIntersection);
		}
	}
	//Check if side 4 intersects (bottom face)
	if(r.direction * n4 != 0){
		tempU = ((n4*(minValues-r.origin))/(r.direction*n4));
		tempIntersection = r.origin+tempU*r.direction;
		if(tempIntersection.x >= minValues.x && tempIntersection.x <= maxValues.x &&
		   tempIntersection.z >= minValues.z && tempIntersection.z <= maxValues.z){
			validIntersections.push_back(tempIntersection);
		}
	}
	//Check if side 5 intersects (left face)
	if(r.direction * n5 != 0){
		tempU = ((n5*(minValues-r.origin))/(r.direction*n5));
		tempIntersection = r.origin+tempU*r.direction;
		if(tempIntersection.y >= minValues.y && tempIntersection.y <= maxValues.y &&
		   tempIntersection.z >= minValues.z && tempIntersection.z <= maxValues.z){
			validIntersections.push_back(tempIntersection);
		}
	}
	//Check if side 6 intersects (right face)
	if(r.direction * n6 != 0){
		tempU = ((n6*(maxValues-r.origin))/(r.direction*n6));
		tempIntersection = r.origin+tempU*r.direction;
		if(tempIntersection.y >= minValues.y && tempIntersection.y <= maxValues.y &&
		   tempIntersection.z >= minValues.z && tempIntersection.z <= maxValues.z){
			validIntersections.push_back(tempIntersection);
		}
	}

	if(validIntersections.size() == 1){
		validIntersections.push_back(validIntersections.at(0));
	}
	else if(validIntersections.size() == 2){
		float distToPointA = (float)validIntersections.at(0).distanceTo(r.origin);
		float distToPointB = (float)validIntersections.at(1).distanceTo(r.origin);
		if(distToPointB < distToPointA){
			Point3 temp = validIntersections.at(0);
			validIntersections.at(0) = validIntersections.at(1);
			validIntersections.at(1) = temp;
		}
	}

	return validIntersections;
}